home *** CD-ROM | disk | FTP | other *** search
- OVROBJ
- Version 1.0
- Ron Schuster
-
- Overview
- -----------------------------------------------------------------------------
- The Turbo Pascal User's Guide shows how to use the BINOBJ utility to link data
- directly into your program by first converting the data into an OBJ file. Such
- "OBJitized" data normally cannot be used in an overlaid unit. This file
- explains the reason for this restriction and provides a convenient method to
- circumvent it.
-
-
- Using OvrObj
- -----------------------------------------------------------------------------
- OvrObj is a small inline macro that returns a pointer to the OBJitized data,
- whether or not the unit is overlaid. To use it, add the OVR_OBJ unit to the
- uses statement in the unit being overlaid. Then you can access the OBJitized
- data as follows:
-
- PtrVar := OvrObj (@ProcName);
-
- ProcName is the procedure name assigned to the OBJitized data. PtrVar is a
- pointer variable of any appropriate type. Alternatively, the pointer returned
- by OvrObj can be dereferenced directly with suitable typecasting. See
- DEMOUNIT.PAS for examples of both approaches.
-
-
- Restrictions
- ----------------------------------------------------------------------------
- 1) OvrObj must be used in the same unit as the data itself. This ensures
- that the data is actually loaded into memory when you access it.
-
- 2) If you assign the value returned by OvrObj to a pointer variable, rather
- than deferencing it directly, its value is only guaranteed to be valid until
- the next time a new unit gets loaded into the overlay buffer. Keep in mind
- that the pointer returned by OvrObj is an address within the overlay buffer.
- Any time the overlay manager gets control, it can, and frequently does, move
- any or all units within the overlay buffer to different memory locations. Any
- such action will invalidate any OvrObj pointers you have stored in variables.
- This can happen when the current procedure ends, or when a call is made to a
- procedure in another overlaid unit, either directly or indirectly.
-
-
- Running the demo
- -----------------------------------------------------------------------------
- Using the BINOBJ program supplied with your copy of Turbo Pascal, convert the
- text file DEMOTEXT.TXT to an OBJ file:
-
- BINOBJ DEMOTEXT.TXT DEMOTEXT.OBJ DEMOTEXT
-
- Then compile DEMO and DEMOUNIT normally. When you run DEMO, the string
- contained in DEMOTEXT.TXT is displayed on the screen twice.
-
-
- Why is OvrObj needed?
- -----------------------------------------------------------------------------
- Borland's documentation suggests that the OBJ files produced by BINOBJ
- shouldn't be used in an overlaid unit. But the problem isn't really that the
- data shouldn't be overlaid. It's just that getting the address of that data is
- much less straightforward when it is overlaid.
-
- First, we'll need a little background about how the overlay system works.
- For the purposes of this discussion, each overlaid unit has two parts: a static
- "dispatcher" segment, and the actual overlaid code. Each static dispatcher is
- a small code segment that's linked into the EXE file. A unique dispatcher
- always remains in memory for each overlaid unit. Whenever you call a procedure
- in an overlaid unit, you're really calling a tiny (5 byte) routine in the
- static dispatcher. If the overlay is already loaded into memory, the 5 byte
- "routine" is just a far jump instruction that immediately transfers control to
- the real code in the overlay buffer. If the overlay isn't currently loaded,
- the 5 bytes specify an INT $3F instruction and one word of data. The INT $3F
- serves to transfer control to the OVERLAY unit, which finds space for the
- overlay (perhaps by booting out other overlays), loads the actual overlay code
- into memory from the OVR file, patches direct jump instructions into the static
- dispatcher, and jumps to the requested procedure. The data word specifies the
- code offset of the routine being called and is used to create the jump
- instruction.
-
- So how does all this relate to OBJitized data? Borrowing from the example on
- page 288 in the Turbo Pascal User's Guide:
-
- procedure MenuData; external;
- {$L MENUDTA.OBJ}
- ...
- ShowScreen(@MenuData);
- ...
-
- In the example in the book, @MenuData will always be equal to the address of
- the actual data since it is defined in the main program. This is also the case
- if you define MenuData in a non-overlaid unit. However, if you overlay that
- unit, the value of @MenuData will be the address of MenuData's 5 byte entry in
- the static dispatcher. Since this is probably not the address you wanted,
- Borland simply recommends that you not do this, but we will use that address
- later to find out where the data really is.
-
- Note that this depends on whether or not the unit is actually overlaid (i.e.,
- does the {$O UnitName} directive appear in the main program?), and not just
- whether unit was compiled with the $O+ directive.
-
-
- Finding the data
- -----------------------------------------------------------------------------
- In the example above, if the unit is overlaid, and the unit has been loaded,
- then @MenuData is the address of the far jump instruction to the actual data.
- Although we don't intend to jump to our data, we can get its address from the
- 5-byte jump instruction. The first byte is the far jump op-code. The
- remaining 4 bytes give us the complete segment and offset address of the actual
- data in the overlay buffer.
-
- Therefore, in order to decide how to handle itself, a unit must first determine
- whether it really has been overlaid. This can be done by looking a offset 0 of
- the unit's segment. If the unit is overlaid this will contain the static
- dispatcher, which always begins with an INT $3F instruction, regardless of
- whether or not the unit is loaded. If you consider that to be a Word, the
- number $3FCD is stored there.
-
- Note that this is not fool-proof. It is possible that a non-overlaid unit may
- have that special number at that particular location. This would occur in the
- unlikely case that the program had range-checking turned on, and the first
- range declared in the unit had a lower bound having $3FCD as its least
- significant 16-bits. This would seem highly unlikely unless a malicious
- attempt is made by the programmer to confuse the "overlay detector". Although
- a more robust check could be written using other known information about the
- static dispatcher format, this would probably be more compiler-version
- dependent, and would certainly be slower. Given its simplicity and extremely
- low probability of failure, the one-word comparison seems the better choice.
-
-
- Putting it all together
- -----------------------------------------------------------------------------
- Now we can see how OvrObj works. First, it checks the word at offset 0 of the
- unit. If it is equal to $3FCD, indicating that the unit is overlaid, then X is
- the address of the far jump instruction in the static dispatcher. Incrementing
- the offset of X by 1 gets us to the address portion of the jump instruction,
- which is the real address of the data. This address is returned to the caller.
-
- If the word at offset 0 is not equal to $3FCD, then the unit is not overlaid
- and the value of X is returned unchanged, since it is the actual address of the
- data.
-
-
- End.
- -----------------------------------------------------------------------------
- OvrObj was written by Ron Schuster. It is copyright (c)1989 by Ron Schuster.
- It may be distributed freely, but not for a profit.
-
- If you have problems, suggestions, or enhancements, please contact me on
- CompuServe [76666,2322].
-
- I first became aware of this technique through the file OBJOVR.ARC by David
- Dubois. Anyone who has implemented the technique as presented in this file
- should be aware that it contains an error that can produce an intermittent
- bug. The problem is in the "overlay detector". It does a two-word (LongInt)
- comparison that assumes that the second word is always zero, which is not
- always true.
-
- Portions of this documentation were adapted from OBJOVR.ARC by David Dubois
- [71401,747] and OVRSIZ.ARC by Kim Kokkonen [76004,2611] with permission from
- the authors. For a more detailed explanation of the internal workings of the
- overlay system, download the file OVRLAY.TXT. These files are all available
- on CompuServe (BPROGA forum LIB 2).